package com.demo.reggie.filter;

import com.alibaba.fastjson.JSON;
import com.demo.reggie.common.BaseContext;
import com.demo.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 检查用户是否已登录
 */
@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    // 工具类：用来进行路径匹配
    public static final PathMatcher PATH_MATCHER = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 定义放行的白名单
        String[] urls = new String[] {
                "/employee/login",
                "/employee/logout",
                "/common/**"
        };

        // 1.获取当前请求的路径
        String requestURI = request.getRequestURI();

        // 2.判断当前请求是否在白名单中，如果在就放行
        if(check(urls, requestURI)) {
            log.info("放行请求：{}", requestURI);
            filterChain.doFilter(request, response);
            return;
        }

        // 3.如果不在白名单，就判断是否登录，如果登录就放行
        if(request.getSession().getAttribute("employee") != null) {
            log.info("已登录，放行");
            // 将当前登录用户的id设置为线程id，方便别的地方获取
            BaseContext.setCurrentId((Long) request.getSession().getAttribute("employee"));
            filterChain.doFilter(request, response);
            return;
        }

        // 4.返回未登录的消息
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
    }

    /**
     * 检查当前请求是否在请求白名单中
     * @param urls 白名单集合
     * @param uri 当前请求路径
     * @return boolean
     */
    public boolean check(String[] urls, String uri) {
        for (String url : urls) {
            // 对当前请求的路径和白名单中的数据进行匹配，如果存在就返回true
            boolean match = PATH_MATCHER.match(url, uri);
            if(match) {
                return true;
            }
        }
        // 白名单循环完成后还没有苑配的数所就返回false
        return false;
    }
}
